use super::builtin::get_builtins;
use async_recursion::async_recursion;
use std::collections::HashMap;

#[derive(Clone)]
pub enum VariableType {
    Number,
    String,
    Boolean,
    Function,
    Referencing,
    Array,
    Binary,
    Null,
    Err,
    FunctionBlock,
}

#[derive(Clone)]
pub enum VariableScopeType {
    Global,
    Builtin,
    Temp,
}

#[derive(Clone)]
pub enum SvmStatus {
    Running,
    Stop,
}

pub enum FunctionExecuteType {
    None,
    Return,
    ReturnVar(String),
}

#[derive(Clone)]
pub enum VariableValue {
    Number(f64),
    String(String),
    Boolean(bool),
    Function(fn(Vec<String>) -> VariableValue),
    Array(Vec<String>),
    Binary(Vec<u8>),
    Null,
    Err(String),
    FunctionBlock(Vec<SvnToken>),
}

impl VariableValue {
    pub fn as_number(&self) -> Option<&f64> {
        match self {
            VariableValue::Number(number) => Some(number),
            _ => None,
        }
    }
    pub fn as_string(&self) -> Option<&String> {
        match self {
            VariableValue::String(string) => Some(string),
            _ => None,
        }
    }

    pub fn as_boolean(&self) -> Option<bool> {
        match self {
            VariableValue::Boolean(bool) => Some(*bool),
            _ => None,
        }
    }

    pub fn as_function(&self) -> Option<&fn(Vec<String>) -> VariableValue> {
        match self {
            VariableValue::Function(func) => Some(func),
            _ => None,
        }
    }
    pub fn as_function_block(&self) -> Option<&Vec<SvnToken>> {
        match self {
            VariableValue::FunctionBlock(block) => Some(block),
            _ => None,
        }
    }
    pub fn as_array(&self) -> Option<&Vec<String>> {
        match self {
            VariableValue::Array(arr) => Some(arr),
            _ => None,
        }
    }
    pub fn as_binary(&self) -> Option<&Vec<u8>> {
        match self {
            VariableValue::Binary(arr) => Some(arr),
            _ => None,
        }
    }
    pub fn is_null(&self) -> bool {
        match self {
            VariableValue::Null => true,
            _ => false,
        }
    }

    pub fn is_err(&self) -> bool {
        match self {
            VariableValue::Err(_e) => true,
            _ => false,
        }
    }

    pub fn as_err(&self) -> Option<String> {
        match self {
            VariableValue::Err(e) => Some(e.to_string()),
            _ => None,
        }
    }

    pub fn get_type(&self) -> VariableType {
        match self {
            VariableValue::Number(_) => VariableType::Number,
            VariableValue::String(_) => VariableType::String,
            VariableValue::Boolean(_) => VariableType::Boolean,
            VariableValue::Function(_) => VariableType::Function,
            VariableValue::Array(_) => VariableType::Array,
            VariableValue::Binary(_) => VariableType::Binary,
            VariableValue::Null => VariableType::Null,
            VariableValue::Err(_) => VariableType::Err,
            VariableValue::FunctionBlock(_) => VariableType::FunctionBlock,
        }
    }
}

#[derive(Clone)]
pub struct ReferencingValue {
    pub name: String,
}

#[derive(Clone)]
pub enum AstTokenType {
    BinaryExpression,
}

#[derive(Clone)]
pub enum OperatorType {
    Add,
    Subtract,
    Multiply,
    Divide,
    Modulo,
    Equal,
    NotEqual,
    LessThan,
    GreaterThan,
    LessThanOrEqual,
    GreaterThanOrEqual,
    And,
    Or,
}

#[derive(Clone)]
pub enum AstBlockType {
    Function,
    CallFunction,
    Logic,
    Loop,
    CountLoop,
    SetVariable,
    ReturnFunction,
    ExecuteFunction,
}

#[derive(Clone)]
pub enum FunType {
    Async,
    Sync,
}
#[derive(Clone)]
pub struct SvnToken {
    pub id: String,
    pub node_id: String,
    pub block: Option<AstBlock>,
    pub scope: String,
    pub args: Option<Vec<ReferencingValue>>,
    pub value: Option<StackValue>,
    pub ast: Option<AstToken>,
}

impl SvnToken {
    pub fn new(id: String,node_id: String, scope: String) -> Self {
        SvnToken {
            id,
            node_id,
            scope,
            block: None,
            args: None,
            value: None,
            ast: None,
        }
    }
}
#[derive(Clone)]
pub struct StackValue {
    pub node_id: String,
    pub id: String,
    pub var_type: VariableType,
    pub value: VariableValue,
    pub scope: String,
    pub scope_type: VariableScopeType,
}

impl StackValue {
    pub fn new(
        node_id: String,
        id: String,
        var_type: VariableType,
        value: VariableValue,
        scope: String,
        scope_type: VariableScopeType,
    ) -> Self {
        StackValue {
            node_id,
            id,
            var_type,
            value,
            scope,
            scope_type,
        }
    }

    pub fn to_string(&self) -> &str {
        &self.id
    }

    pub fn free(&self) {}
}
#[derive(Clone)]
pub struct AstToken {
    pub node_id: String,
    pub id: String,
    pub token_type: AstTokenType,
    pub operator: OperatorType,
    pub left: ReferencingValue,
    pub right: ReferencingValue,
}

impl AstToken {
    pub fn new(
        node_id: String,
        id: String,
        token_type: AstTokenType,
        operator: OperatorType,
        left: ReferencingValue,
        right: ReferencingValue,
    ) -> Self {
        AstToken {
            node_id,
            id,
            token_type,
            operator,
            left,
            right,
        }
    }

    pub fn operate(&self, left: &StackValue, right: &StackValue) -> Option<VariableValue> {
        match (left.var_type.to_owned(), right.var_type.to_owned()) {
            (VariableType::Number, VariableType::Number) => match self.operator {
                OperatorType::Add => Some(VariableValue::Number(
                    left.value.as_number()? + right.value.as_number()?,
                )),
                OperatorType::Subtract => Some(VariableValue::Number(
                    left.value.as_number()? - right.value.as_number()?,
                )),
                OperatorType::Multiply => Some(VariableValue::Number(
                    left.value.as_number()? * right.value.as_number()?,
                )),
                OperatorType::Divide => Some(VariableValue::Number(
                    left.value.as_number()? / right.value.as_number()?,
                )),
                OperatorType::Modulo => Some(VariableValue::Number(
                    left.value.as_number()? % right.value.as_number()?,
                )),
                OperatorType::Equal => Some(VariableValue::Boolean(
                    left.value.as_number()? == right.value.as_number()?,
                )),
                OperatorType::NotEqual => Some(VariableValue::Boolean(
                    left.value.as_number()? != right.value.as_number()?,
                )),
                OperatorType::LessThan => Some(VariableValue::Boolean(
                    left.value.as_number()? < right.value.as_number()?,
                )),
                OperatorType::GreaterThan => Some(VariableValue::Boolean(
                    left.value.as_number()? > right.value.as_number()?,
                )),
                OperatorType::LessThanOrEqual => Some(VariableValue::Boolean(
                    left.value.as_number()? <= right.value.as_number()?,
                )),
                OperatorType::GreaterThanOrEqual => Some(VariableValue::Boolean(
                    left.value.as_number()? >= right.value.as_number()?,
                )),
                _ => None,
            },
            (VariableType::String, VariableType::String) => match self.operator {
                OperatorType::Add => Some(VariableValue::String(format!(
                    "{}{}",
                    left.value.as_string()?,
                    right.value.as_string()?
                ))),
                _ => None,
            },
            (VariableType::Boolean, VariableType::Boolean) => match self.operator {
                OperatorType::And => Some(VariableValue::Boolean(
                    left.value.as_boolean()? && right.value.as_boolean()?,
                )),
                OperatorType::Or => Some(VariableValue::Boolean(
                    left.value.as_boolean()? || right.value.as_boolean()?,
                )),
                OperatorType::Equal => Some(VariableValue::Boolean(
                    left.value.as_boolean()? == right.value.as_boolean()?,
                )),
                OperatorType::NotEqual => Some(VariableValue::Boolean(
                    left.value.as_boolean()? != right.value.as_boolean()?,
                )),
                _ => None,
            },
            _ => None,
        }
    }
}
#[derive(Clone)]
pub struct AstBlock {
    pub node_id: String,
    pub id: String,
    pub block_type: AstBlockType,
    pub body: Vec<SvnToken>,
    pub func_name: Option<String>,
    pub args: Option<Vec<ReferencingValue>>,
    pub fun_type: FunType,
}

impl AstBlock {
    pub fn new(
        node_id: String,
        id: String,
        block_type: AstBlockType,
        body: Vec<SvnToken>,
        func_name: Option<String>,
        args: Option<Vec<ReferencingValue>>,
        fun_type: FunType,
    ) -> Self {
        AstBlock {
            node_id,
            id,
            block_type,
            body,
            func_name,
            args,
            fun_type,
        }
    }
}

pub struct Svm {
    stack: HashMap<String, StackValue>,
    status: SvmStatus,
    tokens: Vec<SvnToken>,
    debug: bool,
    last_scope: Option<String>,
}

impl Svm {
    pub fn new(debug: bool) -> Self {
        let mut svm = Svm {
            stack: HashMap::new(),
            status: SvmStatus::Stop,
            tokens: Vec::new(),
            debug,
            last_scope: None,
        };
        svm.register_builtins();
        return svm;
    }

    pub fn status(&self) -> SvmStatus {
        self.status.clone()
    }

    fn register_builtins(&mut self) {
        let builtins = get_builtins();
        for (key, value) in builtins {
            let value = StackValue::new(
                key.clone(),
                key.clone(),
                VariableType::Function,
                value,
                "".to_owned(),
                VariableScopeType::Builtin,
            );
            self.stack.insert(key, value);
        }
    }

    pub fn register_function(
        &mut self,
        key: String,
        func: fn(Vec<String>) -> VariableValue,
        scope: String,
        scope_type: VariableScopeType,
    ) {
        let value = StackValue::new(
            "".to_string(),
            key.clone(),
            VariableType::Function,
            VariableValue::Function(func),
            scope,
            scope_type,
        );
        self.stack.insert(key, value);
    }

    pub fn register_variable(
        &mut self,
        key: String,
        var_type: VariableType,
        value: VariableValue,
        scope: String,
        scope_type: VariableScopeType,
    ) {
        let old = self.get_variable(&key);
        if let Some(_) = old {
            self.update_variable(key, value);
        } else {
            let val = StackValue::new(
                "".to_string(),
                key.clone(),
                var_type,
                value,
                scope,
                scope_type,
            );
            self.stack.insert(key, val);
        }
    }

    fn clear_stack(&mut self) {
        self.stack.retain(|_, val| match val.scope_type {
            VariableScopeType::Builtin => true,
            VariableScopeType::Temp => false,
            VariableScopeType::Global => false,
        })
    }
    fn get_token(&self, id: &str) -> Option<SvnToken> {
        for t in &self.tokens {
            if t.node_id == id {
                return Some(t.clone());
            }
        }
        None
    }
    pub async fn execute(&mut self, tokens: Vec<SvnToken>) {
        self.status = SvmStatus::Running;
        self.tokens = tokens.clone();
        self.clear_stack();
        if let Err(e) = self.evaluate(&tokens, None).await {
            println!("svm: {}", e);
        }
        self.status = SvmStatus::Stop;
    }

    async fn evaluate(
        &mut self,
        tokens: &Vec<SvnToken>,
        father_id: Option<String>,
    ) -> Result<FunctionExecuteType, String> {
        let mut return_type = FunctionExecuteType::None;
        for token in tokens {
            let is_stop = match self.status {
                SvmStatus::Stop => true,
                SvmStatus::Running => false,
            };
            if is_stop {
                break;
            }
            return_type = self.evaluate_token(token).await?;

            let need_return = match return_type {
                FunctionExecuteType::None => false,
                FunctionExecuteType::Return => true,
                FunctionExecuteType::ReturnVar(_) => true,
            };

            self.last_scope = Some(token.scope.clone());
            if need_return {
                break;
            }
        }

        if let Some(fid) = father_id {
            self.gc_clear_temp(fid);
        }

        Ok(return_type)
    }
    fn find_token_from_id(&self, id: &str,tokens: Option<&Vec<SvnToken>>) -> Option<SvnToken> {
        let mut all_tokens = &self.tokens;
        if let Some(ts) = tokens {
            all_tokens = ts;
        }
        let mut my_token: Option<SvnToken> = None;
        for token in all_tokens {
            if token.node_id == id {
                my_token = Some(token.clone());
                break;
            }else {
                if let Some(block) = &token.block{
                    my_token = self.find_token_from_id(id, Some(&block.body));
                }
            }
        }
        my_token
    }
    fn gc_clear_temp(&mut self, father_id: String) {
        // clear block temp
        let father_temp = self.find_token_from_id(&father_id, None);
        
        if let Some(father) = father_temp {
            let scope = &father.scope;
            if self.debug {
                println!("execute end: {}", father_id);
            }
            
            self.stack.retain(|_, val| {
                let not_builtin = match &val.scope_type {
                    VariableScopeType::Builtin => false,
                    _ => true,
                };
                let not_func = match &val.var_type {
                    VariableType::Function => false,
                    _ => true,
                };
                if &val.scope == scope && not_builtin && not_func {
                    val.free();
                    if self.debug {
                        println!("free: {},scope:{}", val.id, scope);
                    }
                    false
                } else {
                    true
                }
            })
        }
    }
    #[async_recursion]
    async fn evaluate_token(&mut self, token: &SvnToken) -> Result<FunctionExecuteType, String> {
        if let Some(block) = &token.block {
            // block
            let res = match block.block_type {
                AstBlockType::Function => self.set_function(block).await?,
                AstBlockType::CallFunction => self.call_function(block).await?,
                AstBlockType::ReturnFunction => self.set_function_return(block).await?,
                AstBlockType::Logic => self.evaluate_logic(block).await?,
                AstBlockType::Loop => self.evaluate_loop(block).await?,
                AstBlockType::CountLoop => self.evaluate_count_loop(block).await?,
                AstBlockType::SetVariable => self.block_set_variable(block).await?,
                AstBlockType::ExecuteFunction => self.evaluate_function(block).await?,
            };

            return Ok(res);
        } else if let Some(ast) = &token.ast {
            // express
            match ast.token_type {
                AstTokenType::BinaryExpression => self.evaluate_binary_expression(ast)?,
            }
        } else if let Some(val) = token.value.to_owned() {
            // stack value
            self.register_variable(val.id, val.var_type, val.value, val.scope, val.scope_type);
        }
        Ok(FunctionExecuteType::None)
    }

    fn evaluate_binary_expression(&mut self, token: &AstToken) -> Result<(), String> {
        let left = self.get_variable(token.left.name.as_str());
        let left_temp: StackValue;
        if let Some(val) = left {
            left_temp = val.clone();
        } else {
            return Err("left variable undefined".to_string());
        }
        let right = self.get_variable(token.right.name.as_str());
        let right_temp: StackValue;
        if let Some(val) = right {
            right_temp = val.clone();
        } else {
            return Err("right variable undefined".to_string());
        }

        let res = token.operate(&left_temp, &right_temp);
        if let Some(val) = res {
            self.register_variable(
                token.id.clone(),
                VariableType::Number,
                val,
                "/".to_string(),
                VariableScopeType::Temp,
            );
            Ok(())
        } else {
            return Err("operate error".to_string());
        }
    }

    async fn block_set_variable(
        &mut self,
        token: &AstBlock,
    ) -> Result<FunctionExecuteType, String> {
        if let Some(args) = &token.args {
            if args.len() != 2 {
                return Err("set variable args need 2".to_string());
            }

            let val_temp = self.get_variable(args[0].name.as_str());
            let new_val_temp = self.get_variable(args[1].name.as_str());
            if let Some(val) = val_temp {
                if let Some(new_val) = new_val_temp {
                    self.update_variable(val.id.to_string(), new_val.value.clone());
                    self.evaluate(&token.body, Some(token.id.clone())).await?;
                } else {
                    return Err("new variable undefined".to_string());
                }
            } else {
                return Err("update variable undefined".to_string());
            }
        } else {
            return Err("set variable args undefined".to_string());
        }
        Ok(FunctionExecuteType::None)
    }
    #[async_recursion]
    async fn evaluate_logic(&mut self, token: &AstBlock) -> Result<FunctionExecuteType, String> {
        if let Some(args) = &token.args {
            if args.len() != 1 {
                return Err("Logic args undefined".to_string());
            }
            let condition_temp = self.get_variable(args[0].name.as_str());
            let condition;
            if let Some(val) = condition_temp {
                if let Some(v) = &val.value.as_boolean() {
                    condition = *v;
                } else {
                    return Err("Logic args mustbe boolean".to_string());
                }
            } else {
                return Err("Logic args undefined".to_string());
            }

            if condition {
                self.evaluate(&token.body, Some(token.id.clone())).await?;
            }
        }
        Ok(FunctionExecuteType::None)
    }
    #[async_recursion]
    async fn evaluate_loop(&mut self, token: &AstBlock) -> Result<FunctionExecuteType, String> {
        if let Some(args) = &token.args {
            if args.len() != 1 {
                return Err("Loop arg undefined".to_string());
            }
            let arg_name = args[0].name.as_str();
            let condition_temp = self.get_variable(arg_name);
            let mut condition;
            match condition_temp {
                Some(val) => {
                    if let Some(v) = &val.value.as_boolean() {
                        condition = *v;
                    } else {
                        return Err("Loop arg mustbe boolean".to_string());
                    }
                }
                None => {
                    return Err("Loop arg undefined".to_string());
                }
            }
            let arg_token = self.get_token(arg_name);

            while condition {
                match self.status {
                    SvmStatus::Running => {
                        let need_return =
                            match self.evaluate(&token.body, Some(token.id.clone())).await? {
                                FunctionExecuteType::Return => true,
                                FunctionExecuteType::ReturnVar(_) => true,
                                FunctionExecuteType::None => false,
                            };
                        if need_return {
                            break;
                        }

                        if let Some(arg) = &arg_token {
                            if let Some(block) = &arg.block {
                                match block.block_type {
                                    AstBlockType::Function => self.evaluate_function(block).await?,
                                    AstBlockType::CallFunction => self.call_function(block).await?,
                                    _ => FunctionExecuteType::None,
                                };
                            } else if let Some(ast) = &arg.ast {
                                match ast.token_type {
                                    AstTokenType::BinaryExpression => {
                                        self.evaluate_binary_expression(ast)?
                                    }
                                }
                            }
                        }
                        // reset condition
                        let condition_temp = self.get_variable(args[0].name.as_str());
                        if let Some(val) = condition_temp {
                            if let Some(v) = &val.value.as_boolean() {
                                condition = *v;
                            } else {
                                return Err("Loop arg mustbe boolean".to_string());
                            }
                        } else {
                            return Err("Loop arg undefined".to_string());
                        }
                    }
                    SvmStatus::Stop => break,
                }
            }
        } else {
            return Err("Loop args undefined".to_string());
        }
        Ok(FunctionExecuteType::None)
    }

    #[async_recursion]
    async fn evaluate_count_loop(
        &mut self,
        token: &AstBlock,
    ) -> Result<FunctionExecuteType, String> {
        if let Some(args) = &token.args {
            if args.len() != 1 {
                return Err("CountLoop arg undefined".to_string());
            }
            let arg_name = args[0].name.as_str();
            let condition_temp = self.get_variable(arg_name);
            let condition;
            match condition_temp {
                Some(val) => {
                    if let Some(v) = &val.value.as_number() {
                        condition = **v;
                    } else {
                        return Err("CountLoop arg mustbe number".to_string());
                    }
                }
                None => {
                    return Err("CountLoop arg undefined".to_string());
                }
            }
            let arg_token = self.get_token(arg_name);
            let mut count: f64 = 0.0;
            while count < condition {
                match self.status {
                    SvmStatus::Running => {
                        let need_return =
                            match self.evaluate(&token.body, Some(token.id.clone())).await? {
                                FunctionExecuteType::Return => true,
                                FunctionExecuteType::ReturnVar(_) => true,
                                FunctionExecuteType::None => false,
                            };
                        if need_return {
                            break;
                        }

                        match &arg_token {
                            Some(arg) => {
                                if let Some(block) = &arg.block {
                                    match block.block_type {
                                        AstBlockType::Function => {
                                            self.evaluate_function(block).await?
                                        }
                                        AstBlockType::CallFunction => {
                                            self.call_function(block).await?
                                        }
                                        _ => FunctionExecuteType::None,
                                    };
                                } else if let Some(ast) = &arg.ast {
                                    match ast.token_type {
                                        AstTokenType::BinaryExpression => {
                                            self.evaluate_binary_expression(ast)?
                                        }
                                    }
                                }
                            }
                            _ => {}
                        }
                        count += 1.0;
                    }
                    SvmStatus::Stop => break,
                }
            }
        } else {
            return Err("CountLoop args undefined".to_string());
        }
        Ok(FunctionExecuteType::None)
    }
    async fn set_function_return(&self, token: &AstBlock) -> Result<FunctionExecuteType, String> {
        if let Some(args) = &token.args {
            if args.len() > 0 {
                let arg = (&args[0].name).clone();
                return Ok(FunctionExecuteType::ReturnVar(arg));
            }
        }
        Ok(FunctionExecuteType::Return)
    }
    async fn set_function(&mut self, token: &AstBlock) -> Result<FunctionExecuteType, String> {
        let id = token.id.clone();
        let scope = String::new();
        let scope_type = VariableScopeType::Global;
        let value = VariableValue::FunctionBlock(token.body.clone());

        self.register_variable(id, VariableType::FunctionBlock, value, scope, scope_type);
        Ok(FunctionExecuteType::None)
    }
    async fn evaluate_function(&mut self, token: &AstBlock) -> Result<FunctionExecuteType, String> {
        let mut fun_name = String::new();
        if let Some(call_args) = &token.args {
            if call_args.len() < 1 {
                return Err(format!(
                    "{} call function need func_name",
                    token.node_id.as_str()
                ));
            }
            let func_name_key = &call_args[0];
            let func_name_temp = self.get_variable(&func_name_key.name).cloned();
            if let Some(fun_name_val) = func_name_temp {
                if let Some(s) = fun_name_val.value.as_string() {
                    fun_name = s.to_owned();
                }
                let args_name_key = format!("{}argsNumber", fun_name);
                let mut args_num = 0.0;
                if let Some(args_val) = self.get_variable(&args_name_key) {
                    args_num = match args_val.value.as_number() {
                        Some(n) => n.to_owned(),
                        None => 0.0,
                    }
                }
                if call_args.len() - 1 < args_num as usize {
                    return Err(format!(
                        "{} call function args need {}",
                        token.node_id.as_str(),
                        args_num
                    ));
                }
                let mut i = 0.0;
                while i < args_num {
                    let val_key = format!("{}_args_{}", fun_name, i);
                    let scope = String::new();
                    let scope_type = VariableScopeType::Temp;
                    let index = i + 1.0;
                    let arg_name = &call_args[index as usize].name;
                    let value = VariableValue::String(arg_name.clone());
                    self.set_variable(val_key, value, scope, scope_type, VariableType::Referencing);
                    i += 1.0
                }
            } else {
                return Err(format!(
                    "{} call function name undefined",
                    token.node_id.as_str()
                ));
            }
        }
        if let Some(func_temp) = self.get_variable(&fun_name).cloned() {
            if let Some(func_block) = func_temp.value.as_function_block() {
                let res = self.evaluate(func_block, Some(token.id.clone())).await?;
                let last_return = match &res {
                    FunctionExecuteType::ReturnVar(ret_val) => {
                        let val = VariableValue::String(ret_val.clone());
                        self.set_variable(
                            token.id.clone(),
                            val.clone(),
                            String::new(),
                            VariableScopeType::Temp,
                            VariableType::Referencing,
                        );
                        let last_res = self.evaluate(&token.body, Some(token.id.clone())).await?;
                        last_res
                    }
                    FunctionExecuteType::Return => FunctionExecuteType::Return,
                    FunctionExecuteType::None => FunctionExecuteType::None,
                };
                return Ok(last_return);
            } else {
                return Err(format!(
                    "{} call function not function block",
                    token.node_id.as_str()
                ));
            }
        } else {
            return Err(format!(
                "{} call function undefined",
                token.node_id.as_str()
            ));
        }
    }

    async fn call_function(&mut self, token: &AstBlock) -> Result<FunctionExecuteType, String> {
        let mut func_name: String;
        if let Some(f) = &token.func_name {
            func_name = f.to_string();
        } else {
            return Err(format!(
                "{} call function need func_name",
                token.node_id.as_str()
            ));
        }
        if func_name == "print" && self.debug {
            func_name = "printVM".to_string();
        }
        let func_temp = self.get_variable(&func_name);
        if let Some(val) = func_temp {
            if let Some(func) = val.value.as_function() {
                let mut args = Vec::new();
                if let Some(args_temp) = &token.args {
                    args = args_temp.clone();
                }
                let mut str_args: Vec<String> = Vec::new();
                for arg in args {
                    let val_temp = self.get_variable(arg.name.as_str());
                    if let Some(val) = val_temp {
                        if let Some(s) = val.value.as_string() {
                            str_args.push(s.to_string());
                        } else if let Some(s) = val.value.as_number() {
                            str_args.push(s.to_string());
                        } else if let Some(s) = val.value.as_boolean() {
                            str_args.push(s.to_string());
                        } else if let Some(s) = val.value.as_array() {
                            str_args.push(s.join(","));
                        } else if let Some(s) = val.value.as_binary() {
                            let temp_ar = s.iter().map(|x| x.to_string()).collect::<Vec<String>>();
                            str_args.push(temp_ar.join(","));
                        }
                    } else {
                        return Err(format!(
                            "function ' {} ' arg {} undefined",
                            &func_name,
                            arg.name.as_str()
                        ));
                    }
                }
                let res = func(str_args.clone());
                if res.is_err() {
                    if let Some(e) = res.as_err() {
                        return Err(format!("call function ' {} ' {}", &func_name, e));
                    } else {
                        return Err(format!("call function  '{} ' unknown error", &func_name));
                    }
                } else if !res.is_null() {
                    // cache var
                    self.register_variable(
                        token.id.clone(),
                        res.get_type(),
                        res,
                        "".to_string(),
                        VariableScopeType::Temp,
                    )
                }
                // body
                self.evaluate(&token.body, Some(token.id.clone())).await?;
            } else {
                return Err("function err".to_string());
            }
        } else {
            return Err(format!("call function ' {} ' undefined", func_name));
        }
        Ok(FunctionExecuteType::None)
    }

    fn get_variable(&self, key: &str) -> Option<&StackValue> {
        let mut val;
        val = self.stack.get(key);

        if val.is_some() {
            if let Some(v) = val {
                match v.var_type {
                    VariableType::Referencing => {
                        // var referencing
                        let val_key = v.value.as_string();
                        if let Some(k) = val_key {
                            val = self.get_variable(k);
                        } else {
                            val = None;
                        }
                    }
                    _ => {}
                }
            }
        }
        return val;
    }

    pub fn set_variable(
        &mut self,
        key: String,
        value: VariableValue,
        scope: String,
        scope_type: VariableScopeType,
        var_type: VariableType,
    ) {
        let val = self.get_variable(&key);

        if let Some(_val) = val {
            self.update_variable(key, value);
        } else {
            self.register_variable(key, var_type, value, scope, scope_type);
        }
    }

    fn update_variable(&mut self, key: String, value: VariableValue) {
        if let Some(val) = self.stack.get_mut(&key) {
            val.value = value;
        }
    }

    pub fn stop(&mut self) {
        self.status = SvmStatus::Stop;
    }
}
